//
// Created by root on 6/29/17.
//

#ifndef FUNNY_SCHEME_CELL_H
#define FUNNY_SCHEME_CELL_H

#include "tree.h"

struct _Cell;
struct _Scheme;
typedef struct _Cell* (*OperatorFunc)(struct _Scheme *);

typedef struct _Pair {
    struct _Cell *_car;
    struct _Cell *_cdr;
} Pair;

typedef struct _Cell {
    unsigned int _flag;  //mark-sweep immutable
    const char *_type;
    const char *_name;
    union {
        long _longValue;
        double _doubleValue;
        char *_string;
        void *_pointer;
        OperatorFunc _op;
        // ForeignFunc _func;
        Pair _pair;
    };
} Cell;

#define CELL_SEGSIZE 5000	 /* # of cells in one segment */
#define CELL_NSEGMENT 100    /* # of segments for cells */
#define CLASS_ITEMS_SIZE 13
#define SYMBOL_POOL_SIZE 461

typedef struct _Scheme {
    Cell* cellSeg[CELL_NSEGMENT];
    int lastCellSeg;
    Cell* freeCell; /* cell* to top of free cells */
    long freeCellCount; /* # of free cells */

    /* We use 4 registers. */
    // OperatorFunc op;							//当前处理方法
    Cell* op;
    Cell* args; /* register for arguments of function */
    Cell* env;  /* stack register for current environment */
    Cell* code; /* register for current code */
    Cell* obj;  /* register for current object */
    Cell* callStack; /* stack register for next evaluation */
    Cell* returnValue;

    char* opString;
    char* argsString;
    char* envString;
    char* codeString;
    char* returnValueString;

    char* input;
    int inputPointer;

    // Cell* objectList; /* cell* to symbol table *///管理所有的符号，确保了所有相同名字的符号是同一个
    Cell* globalObjects; /* cell* to symbol table */
    Cell* symbols; /* cell* to symbol references */
    Cell* globalEnv; /* cell* to global environment */

    Tree* inheritance; /* class hierarchy */
    // Cell* classes; /* class objects */ can find in globalObjects

    int token;						//保持词法分析获取的单词

    /* global cell*s to special symbols */
    //Cell* sym_lambda; /* cell* to syntax lambda */
    //Cell* sym_quote; /* cell* to syntax quote */			//引用    '
    //Cell* sym_feed_to; /* => */							// cond中有用到
    //Cell* sym_colon_hook; /* *colon-hook* */
    //Cell* sym_error_hook; /* *error-hook* */
    //Cell* sym_sharp_hook; /* *sharp-hook* */
    //Cell* sym_this; /* *this* */

    char* basePath;
    char* filePath;
    Queue *loadedFiles;
} Scheme;


// 特征标记
// #define TYPE_MASK       31		/* 0000000000011111 */	// 5位 可以表示32个类型
//#define T_SYNTAX        4096	/* 0001000000000000 */  // 语法符号
//#define T_IMMUTABLE     8192	/* 0010000000000000 */	// 标记一个cell为不可改变的
//#define T_PRIMITIVE     16384	/* 0100000000000000 */	// 标记一个cell为primitive types

#define REF_POINTER     8192	/* 0010000000000000 */	// make a cell as pointer
#define REF_IMMUTABLE   16384	/* 0100000000000000 */	// 标记一个cell为不可改变的
#define REF_MARK        32768	/* 1000000000000000 */	/* 仅用于gc */

int is_pointer(Cell* p);
int is_variable(Cell* p);
int is_constant(Cell* p);
void set_pointer(Cell* p);
int is_immutable(Cell* p);
void set_immutable(Cell* p);
int is_mark(Cell* p);
void set_mark(Cell* p);
void clear_mark(Cell* p);

/* () is #t in R5RS */ //不为#f的都是true
#define is_true(p)       ((p) != G_FALSE)
#define is_false(p)      ((p) == G_FALSE)

Cell *alloc_cell();
Cell* make_cell(Scheme *sc, Cell* a, Cell* b);
int alloc_cellseg(Scheme *sc, int n);

/*
 * car/cdr/cons函数
 * */
Cell* car(Cell* p);
Cell* cdr(Cell* p);
Cell* cons(Scheme *sc, Cell* a, Cell* b);
Cell* immutable_cons(Scheme *sc, Cell* a, Cell* b);

typedef void (*SCHEME_GC)(struct _Scheme *, struct _Cell*, struct _Cell*);


#define CAR(p)           ((p)->_pair._car)
#define CDR(p)           ((p)->_pair._cdr)
#define CAAR(p)          CAR(CAR(p))
#define CADR(p)          CAR(CDR(p))
#define CDAR(p)          CDR(CAR(p))
#define CDDR(p)          CDR(CDR(p))

#define caar(p)   car(car(p))
#define cadr(p)   car(cdr(p))
#define cdar(p)   cdr(car(p))
#define cddr(p)   cdr(cdr(p))
#define caaar(p)  car(car(car(p)))
#define caadr(p)  car(car(cdr(p)))
#define cadar(p)  car(cdr(car(p)))
#define caddr(p)  car(cdr(cdr(p)))
#define cdaar(p)  cdr(car(car(p)))
#define cdadr(p)  cdr(car(cdr(p)))
#define cddar(p)  cdr(cdr(car(p)))
#define cdddr(p)  cdr(cdr(cdr(p)))
#define caaaar(p) car(car(car(car(p))))
#define caaadr(p) car(car(car(cdr(p))))
#define caadar(p) car(car(cdr(car(p))))
#define caaddr(p) car(car(cdr(cdr(p))))
#define cadaar(p) car(cdr(car(car(p))))
#define cadadr(p) car(cdr(car(cdr(p))))
#define caddar(p) car(cdr(cdr(car(p))))
#define cadddr(p) car(cdr(cdr(cdr(p))))
#define cdaaar(p) cdr(car(car(car(p))))
#define cdaadr(p) cdr(car(car(cdr(p))))
#define cdadar(p) cdr(car(cdr(car(p))))
#define cdaddr(p) cdr(car(cdr(cdr(p))))
#define cddaar(p) cdr(cdr(car(car(p))))
#define cddadr(p) cdr(cdr(car(cdr(p))))
#define cdddar(p) cdr(cdr(cdr(car(p))))
#define cddddr(p) cdr(cdr(cdr(cdr(p))))

#define first(p)  	car(p)
#define second(p) 	car(cdr(p))
#define third(p)  	car(cdr(cdr(p)))
#define fourth(p) 	car(cdr(cdr(cdr(p))))
#define fifth(p)  	car(cdr(cdr(cdr(cdr(p)))))
#define sixth(p)  	car(cdr(cdr(cdr(cdr(cdr(p))))))
#define seventh(p)  car(cdr(cdr(cdr(cdr(cdr(cdr(p)))))))
#define eighth(p)  	car(cdr(cdr(cdr(cdr(cdr(cdr(cdr(p))))))))
#define ninth(p)  	car(cdr(cdr(cdr(cdr(cdr(cdr(cdr(cdr(p)))))))))
#define tenth(p)  	car(cdr(cdr(cdr(cdr(cdr(cdr(cdr(cdr(cdr(p))))))))))
#define eleventh(p) car(cdr(cdr(cdr(cdr(cdr(cdr(cdr(cdr(cdr(cdr(p)))))))))))
#define twelfth(p)  car(cdr(cdr(cdr(cdr(cdr(cdr(cdr(cdr(cdr(cdr(cdr(p))))))))))))

#define rest(p)   	cdr(p)

#define DEFINE_OPERATOR(_opname)      Cell* cell_op_##_opname; Cell* op_##_opname(Scheme *)
#define DEFINE_SYNTAX(_syntaxname)    Cell* cell_syntax_##_syntaxname
#define INIT_CONSTANTS(_typename)     void init_##_typename##_constants(Scheme *sc)
#define INIT_OPERATORS(_typename)     void init_##_typename##_operators(Scheme *sc)

#endif //FUNNY_SCHEME_CELL_H
